#include <stdio.h>
#include <fstream>

#include "rawbfileplugin.h"
#include "../../data/bio.h"
#include "../../data/geometrydata.h"

#include "ballview_file.h"

using namespace PBVP;

DataInterface* RawBinFilePlugin::loadFile(const QString &fname)
{
	BALL::BinaryFileAdaptor<float> float_ad;
	BALL::BinaryFileAdaptor<BALL::Size>   size_ad;
	BALL::BinaryFileAdaptor<char>   char_ad;

	BALL::String filename(fname.toStdString());
	BALL::File infile(filename, std::ios::in|std::ios::binary);
	int nv, nt, nc;
	infile >> size_ad >> nv;
	infile >> size_ad >> nt;
	infile >> size_ad >> nc;

	GeometryData *pGeo = new GeometryData();

	for (int i = 0; i < nv; i++) {
		float x, y, z;

		infile >> float_ad >> x;
		infile >> float_ad >> y;
		infile >> float_ad >> z;
		Vector3 vertex(x, y, z);
		pGeo->addVertex(vertex);
	}

	for (int i = 0; i < nv; i++) {
		float nx, ny, nz;
		infile >> float_ad >> nx;
		infile >> float_ad >> ny;
		infile >> float_ad >> nz;
		Vector3 normal(nx, ny, nz);
		pGeo->addNormal(normal);
	}

	for (int i = 0; i < nt; i++) {
		int index[3];
		infile >> size_ad >> index[0];
		infile >> size_ad >> index[1];
		infile >> size_ad >> index[2];
		pGeo->addTriangle(index);
	}

	if (nc == nv) {	 // Each vertex has color attribute
		unsigned char r,g,b,a;
		for (int i = 0; i < nc; i++) {
			infile >> char_ad >> r;
			infile >> char_ad >> g;
			infile >> char_ad >> b;
			infile >> char_ad >> a;
			Vector3 color(r/255.0f, g/255.0f, b/255.0f);
			pGeo->addColor(color);
		}
	}
	infile.close();

	return pGeo;
}

bool RawBinFilePlugin::saveFile(DataInterface *pData, const QString &fname)
{
	GeometryData *pGeo = dynamic_cast<GeometryData *>(pData);
	if(!pGeo) {
		return false;
	}

	BALL::BinaryFileAdaptor<float> float_ad;
	BALL::BinaryFileAdaptor<BALL::Size>   size_ad;
	BALL::BinaryFileAdaptor<char>   char_ad;

	BALL::String filename(fname.toStdString());
	BALL::File outfile(filename, std::ios::out|std::ios::binary);
	int nv = pGeo->numOfVertices();
	int nt = pGeo->numOfTriangles();
	int nc = nv;
	outfile << size_ad << nv;
	outfile << size_ad << nt;
	outfile << size_ad << nc;
	for (unsigned int i = 0; i < nv; i++) {
		Vector3 v = pGeo->getVertex(i);
        outfile << float_ad << v.x;
		outfile << float_ad << v.y;
		outfile << float_ad << v.z;
	}

	for (unsigned int i = 0; i < nv; i++) {
		Vector3 n(0.0f, 0.0f, 1.0f);
		if(pGeo->hasNormalArray()) {
			n = pGeo->getNormalVector(i);
		}
		outfile << float_ad << n.x;
		outfile << float_ad << n.y;
		outfile << float_ad << n.z;
	}

	for (unsigned int i = 0; i < nt; i++) {
		unsigned int idx[3];
		pGeo->getTriangleIndex(i, idx);
		outfile << size_ad << idx[0];
		outfile << size_ad << idx[1];
		outfile << size_ad << idx[2];
	}
	
	for (unsigned int i = 0; i < nc; i++) {
		Vector3 c(0.2f, 0.8f, 0.2f);
		unsigned char r, g, b, a;
		if(pGeo->hasColorArray()) {
			c = pGeo->getColorVector(i);
		}
		r = (unsigned char) (c.x * 255);
		g = (unsigned char) (c.y * 255);
		b = (unsigned char) (c.z * 255);
		a = (unsigned char) 255;
		outfile << char_ad << r;
		outfile << char_ad << g;
		outfile << char_ad << b;
		outfile << char_ad << a;
	}
	outfile.close();
	return true;
}

Q_EXPORT_PLUGIN2(rawbfile, RawBinFilePlugin)